package core.validate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Holder {
    private boolean globalStatus = true;
    private String handle = null;
    private final Map<String, Object> origin;
    private final Map<String, HolderLibraryItem> library = new HashMap<>();

    public Holder(Map<String, Object> origin){
        this.origin = origin;
    }
    @SuppressWarnings("unchecked")
    public <T> T getOrigin(){
        return (T) origin;
    }
    @SuppressWarnings("unchecked")
    public <T> T getOrigin(String key){
        if(origin.containsKey(key)){
            return (T) origin.get(key);
        }else{
            return null;
        }
    }

    public Holder setOrigin(Map<String, Object> request){
        origin.putAll(request);
        return this;
    }

    public Holder setOrigin(String key, Object value){
        origin.put(key, value);
        return this;
    }

    public String getHandle(){
        return handle;
    }

    public Holder setHandle(String handle){
        this.handle = handle;
        if(!library.containsKey(handle)){
            library.put(handle , new HolderLibraryItem(){{
                setValue(getOrigin(handle));
            }});
        }
        return this;
    }

    @SuppressWarnings("unchecked")
    public <T> T getValue(){
        if(handle != null && library.containsKey(handle)){
            return (T) library.get(handle).getValue();
        }
        return null;
    }

    public Map<String, Object> getValues(){
        Map<String, Object> values = new HashMap<>();
        for(Map.Entry<String, HolderLibraryItem> entry: library.entrySet()){
            values.put(entry.getKey(), entry.getValue().getValue());
        }
        return values;
    }

    public Holder setValue(Object value){
        if(handle != null && library.containsKey(handle)){
            library.get(handle).setValue(value);
        }
        return this;
    }

    public boolean getStatus(){
        if(handle != null && library.containsKey(handle)){
            return library.get(handle).getStatus();
        }
        return false;
    }

    public Holder setStatus(boolean status){
        if(handle != null && library.containsKey(handle)){
            library.get(handle).setStatus(status);
            if(globalStatus && !status){
                this.setGlobalStatus(false);
            }
        }
        return this;
    }

    public String getMessage(){
        if(handle != null && library.containsKey(handle)){
            return library.get(handle).getMessage();
        }
        return "";
    }

    public Map<String, String> getMessages(){
        Map<String, String> messages = new HashMap<>();
        for(Map.Entry<String, HolderLibraryItem> entry: library.entrySet()){
            if(!entry.getValue().getStatus()){
                messages.put(entry.getKey(), entry.getValue().getMessage());
            }
        }
        return messages;
    }

    public Holder setMessage(String message){
        if(handle != null && library.containsKey(handle)){
            library.get(handle).setMessage(message);
        }
        return this;
    }

    public boolean getGlobalStatus(){
        return globalStatus;
    }

    public Holder setGlobalStatus(boolean globalStatus) {
        this.globalStatus = globalStatus;
        return this;
    }

    @SuppressWarnings("unchecked")
    public boolean isEmpty(){
        if(handle == null){
            return true;
        }else if(!origin.containsKey(handle)){
            return true;
        }else{
            Object value = origin.get(handle);
            if(value == null){
                return true;
            }else if(value instanceof String strValue){
                return strValue.isEmpty();
            }else if(value instanceof List){
                List<Object> arrValue = (List<Object>) value;
                return arrValue.isEmpty();
            }else if(value instanceof Map){
                Map<String, Object> objValue = (Map<String, Object>) value;
                return objValue.isEmpty();
            }else{
                //return !(value instanceof Boolean);
                return false;
            }
        }
    }
}
